<template>
    <div class="page">
        <p>雷达图</p>
        <div id="container"></div>
    </div>
</template>
<script>
import * as d3 from "d3"
export default {
    data() {
        return {
            radarData: [
                { name: "基础经营能力", max: 100, value: 83 },
                { name: "基础经营保障能力", max: 100, value: 73 },
                { name: "守信经营能力", max: 100, value: 90 },
                { name: "项目履约能力", max: 100, value: 37 },
                { name: "基础竞争力", max: 100, value: 40 }
            ]
        }
    },
    methods: {
        draw() {
            this.initChart()
            //画出雷达图轴线
            this.renderAxis()
            //渲染每个顶点代表的含义文字
            this.renderLabel()
            //渲染实际的数据
            this.renderRealData()
        },
        initChart() {
            this.colors = d3.schemeCategory10
            //先把svg标签输出
            let container = document.querySelector("#container")
            this.tickNum = 3 //这里先写死 使用两个刻度线
            this.svgWidth = container.clientWidth
            this.svgHeight = container.clientHeight
            this.radarRadius =
                d3.min([this.svgWidth - 30, this.svgHeight - 70]) / 2
            this.svg = d3
                .select("#container")
                .append("svg")
                .attr("width", this.svgWidth)
                .attr("height", this.svgHeight)
        },
        getPointers() {
            let points = [],
                dataLen = this.radarData.length
            if (dataLen < 3) {
                //小于三个点没有办法画雷达图
                return
            }
            let anglePiece = (Math.PI * 2) / dataLen,
                radiusReduce = this.radarRadius / this.tickNum
            for (let i = 0; i < this.tickNum; i++) {
                let sque = []
                for (let j = 0; j < dataLen; j++) {
                    let r = this.radarRadius - radiusReduce * i
                    sque.push(
                        [
                            Math.sin(j * anglePiece) * r,
                            -Math.cos(j * anglePiece) * r
                        ].join(",")
                    )
                }
                points.push(sque.join(" "))
            }
            return points
        },
        getOuterPoints(outerPoints) {
            const points = outerPoints.split(" ").map(d => d.split(","))
            return points
        },
        //画雷达图的轴线
        renderAxis() {
            let dataLen = this.radarData.length,
                anglePiece = (Math.PI * 2) / dataLen
            console.log(anglePiece)
            //算坐标点
            let points = this.getPointers()
            let axes = this.svg
                .append("g")
                .attr("class", "axes")
                .attr(
                    "transform",
                    `translate(${this.svgWidth / 2},${this.svgHeight / 2})`
                )
                .selectAll(".axis")
                .data(points)
            axes.enter()
                .append("polygon")
                .attr("class", "axis")
                .attr("points", d => d)
                .attr("stroke", (d, i) => this.colors[i])
                .attr("fill", "none")
            axes.exit().remove()
            //画 对角线
            let outerPoints = this.getOuterPoints(points[0]),
                lineCreator = d3.line()
            let lineUpdate = d3
                .select(".axes")
                .selectAll(".line")
                .data(outerPoints)
            lineUpdate
                .enter()
                .append("path")
                .attr("d", d => lineCreator([[0, 0], d]))
                .attr("stroke-width", 1)
                .attr("stroke", "#000"),
                lineUpdate.exit().remove()
        },
        //画每个顶点代表的含义
        renderLabel() {
            let textUpdate = d3
                    .select(".axes")
                    .selectAll(".label")
                    .data(this.radarData),
                dataLen = this.radarData.length
            textUpdate
                .enter()
                .append("text")
                .attr(
                    "x",
                    (d, i) =>
                        Math.sin((i * Math.PI * 2) / dataLen) *
                        (this.radarRadius + 20)
                )
                .attr(
                    "y",
                    (d, i) =>
                        -Math.cos((i * Math.PI * 2) / dataLen) *
                        (this.radarRadius + 20)
                )
                .text(d => d.name)
                .attr("text-anchor", (d, i) => {
                    let data = this.radarData
                    if (data.length < 3) return

                    const angle = (i * 360) / data.length

                    if (angle === 0 || Math.abs(angle - 180) < 0.01) {
                        return "middle"
                    } else if (angle > 180) {
                        return "end"
                    } else {
                        return "start"
                    }
                })
                .attr("dy", 6.5)
        },
        //画 出代表 真实数据 的多边形
        renderRealData() {
            let dataLen = this.radarData.length,
                anglePiece = (Math.PI * 2) / dataLen,
                realDataPoints = []
            //定义比例尺，为每一个维度定义比例尺
            this.radarData.forEach((item, index) => {
                let symbol = Symbol.for(item.name)
                this[symbol] = d3
                    .scaleLinear()
                    .domain([0, item.max])
                    .range([0, this.radarRadius])
                realDataPoints.push(
                    [
                        Math.sin(index * anglePiece) * this[symbol](item.value),
                        -Math.cos(index * anglePiece) * this[symbol](item.value)
                    ].join(",")
                )
            })
            this.svg
                .selectAll(".polygons")
                .data([""])
                .enter()
                .append("g")
                .attr("class", "polygons")
                .attr(
                    "transform",
                    `translate(${this.svgWidth / 2},${this.svgHeight / 2})`
                )
                .selectAll(".polygon")
                .data([realDataPoints.join(" ")])
                .enter()
                .append("polygon")
                .attr("class", "polygon")
                // .attr("points", d => d)
                .attr("fill", "none")
                .attr("stroke-width", 1)
                .attr("stroke", (d, i) => this.colors[i])
                .transition()
                .duration(2)
                .attr('points',d=>d)
        }
    },
    mounted() {
        this.draw()
    }
}
</script>
<style lang="css" scoped>
#container {
    height: 500px;
}
</style>
